home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 276-300 / disk_280 / graph / gadgets / gadgets.c
C/C++ Source or Header  |  1992-05-06  |  38KB  |  1,307 lines

  1. /* Routines to create various types of gadgets, menus, etc
  2.    Could do with a few comments and some documentation ...
  3.    This code is placed in the public domain.
  4.    David Gay, 1989.
  5. */
  6.  
  7. #include <proto/exec.h>
  8. #include <exec/nodes.h>
  9. #include <exec/lists.h>
  10. #include <exec/memory.h>
  11. #include <graphics/gfx.h>
  12. #include <intuition/intuition.h>
  13. #include <proto/graphics.h>
  14. #include <proto/intuition.h>
  15. #include <proto/diskfont.h>
  16. #include "user/gadgets.h"
  17. #include <string.h>
  18.  
  19. #define XDOUBLEMARGIN   4                   /* Margin for "double" border reque
  20. sters */
  21. #define YDOUBLEMARGIN   4
  22. #define GADGTEXTX       4                   /* How far away (X) text is from Op
  23. tion/Radio gadgets */
  24. #define GADGTEXTY       4                   /* idem, but when text above gadget
  25.  */
  26. #define TEXTBORDERX     2                   /* How far out text gadget rectangl
  27. e is */
  28. #define TEXTBORDERY     4
  29. #define MENUMARGIN      20                  /* Spacing between menus */
  30. #define TEXTMARGIN      10                  /* Space around text items */
  31. #define TEXTGAP         2                   /* Space above & below text items *
  32. /
  33. #define RULEHEIGHT      2                   /* Height of rules */
  34. #define RULEGAP         6                   /* Space above & below rules */
  35. #define RULEMARGIN      10                  /* idem, but left & right */
  36. #define MINITEMWIDTH    (RULEMARGIN + 10)   /* Min. menu item width */
  37. #define SUBX            30                  /* Sub item position */
  38.  
  39. boolean CheckFont(struct Memory *);
  40.  
  41. struct Memory
  42. {
  43.     struct MinList Fonts;
  44.     struct MinList Lists;
  45.     struct Remember *Mem;
  46. };
  47.  
  48. struct FontNode
  49. {
  50.     struct MinNode fn_Node;
  51.     struct TextFont *font;
  52. };
  53.  
  54. struct ITextNode
  55. {
  56.     struct MinNode it_node;
  57.     struct IntuiText it;
  58. };
  59.  
  60. typedef struct Gadget GArray[1];
  61.  
  62. struct ListInfo
  63. {
  64.     struct MinNode li_node;
  65.     char *buf;
  66.     long len;
  67.     struct List *list;
  68.     struct MinList ilist;
  69.     struct IntuiText *blank;
  70.     long nb, current, pos;
  71.     struct Gadget *arrow1, *arrow2, *strg, *sld;
  72.     GArray *glist;
  73.     long visible, exists, dispchars;
  74.     ULONG clicksecs, clickmics;
  75.     long clickpos;
  76. };
  77.  
  78. static struct TextAttr topaz8 = { "topaz.font", 8 };
  79. static BYTE fore = 1, back = 0, mode = JAM1, depth = 2;
  80. static struct TextAttr *ta = &topaz8;
  81. static boolean fontopen;
  82. static struct TextFont *font;
  83.  
  84.  
  85. static UWORD chip down_data[] = {
  86.         0xF83E,0xF83E,0xF83E,0xC006,0xE00E,0xF01E,0xF83E,0xFC7E,
  87.         0xFEFE,0xFFFE,0x07C0,0x07C0,0x07C0,0x3FF8,0x1FF0,0x0FE0,
  88.         0x07C0,0x0380,0x0100,0x0000
  89. };
  90.  
  91. static struct Image down_img = {
  92.         0, 1,
  93.         15, 10,
  94.         2,
  95.         down_data,
  96.         0x0003, 0x0000,
  97.         NULL
  98. };
  99.  
  100. static UWORD chip up_data[] = {
  101.         0xFEFE,0xFC7E,0xF83E,0xF01E,0xE00E,0xC006,0xF83E,0xF83E,
  102.         0xF83E,0xFFFE,0x0100,0x0380,0x07C0,0x0FE0,0x1FF0,0x3FF8,
  103.         0x07C0,0x07C0,0x07C0,0x0000
  104. };
  105.  
  106. static struct Image up_img = {
  107.         0, 1,
  108.         15, 10,
  109.         2,
  110.         up_data,
  111.         0x0003, 0x0000,
  112.         NULL
  113. };
  114.  
  115. /* Returns number of nodes, or -1 for failure */
  116. static long build_ilist(struct ListInfo *li)
  117. {
  118.     int cnt = 0;
  119.     struct Node *scan;
  120.  
  121.     NewList((struct List *)&li->ilist);
  122.  
  123.     for (scan = li->list->lh_Head; scan->ln_Succ; scan = scan->ln_Succ, cnt++)
  124.     {
  125.         struct ITextNode *in = AllocMem(sizeof(struct ITextNode) + li->dispchar
  126. s + 1, MEMF_CLEAR);
  127.         char *str;
  128.         struct IntuiText *it;
  129.         int j;
  130.  
  131.         if (!in) return -1;
  132.         it = (struct IntuiText *)&in->it;
  133.         str = (char *)(in + 1);
  134.  
  135.         str[li->dispchars] = '\0';
  136.  
  137.         strncpy(str, scan->ln_Name, li->dispchars);
  138.         for (j = strlen(str); j < li->dispchars; j++) str[j] = ' ';
  139.  
  140.         it->FrontPen = fore; it->BackPen = back;
  141.         it->DrawMode = JAM2;
  142.         it->ITextFont = ta;
  143.         it->IText = str;
  144.  
  145.         AddTail((struct List *)&li->ilist, (struct Node *)in);
  146.     }
  147.     li->exists = li->visible > cnt ? cnt : li->visible;
  148.     return cnt;
  149. }
  150.  
  151. static void free_ilist(struct ListInfo *li)
  152. {
  153.     struct MinNode *scan, *next;
  154.  
  155.     for (scan = li->ilist.mlh_Head; next = scan->mln_Succ; scan = next)
  156.         FreeMem(scan, sizeof(struct ITextNode) + li->dispchars + 1);
  157. }
  158.  
  159. static void recalc_glist(struct ListInfo *li)
  160. {
  161.     int i;
  162.     struct ITextNode *scan;
  163.  
  164.     for (i = 0, scan = (struct ITextNode *)li->ilist.mlh_Head; i < li->pos; i++
  165. , scan = (struct ITextNode *)scan->it_node.mln_Succ)
  166.         ;
  167.     for (i = 0; i < li->exists; i++, scan = (struct ITextNode *)scan->it_node.m
  168. ln_Succ)
  169.         (*li->glist)[i].GadgetText = &scan->it;
  170.     for (; i < li->visible; i++)
  171.         (*li->glist)[i].GadgetText = li->blank;
  172.  
  173.     if (li->current >= li->pos && li->current < li->pos + li->exists)
  174.         (*li->glist)[li->current - li->pos].Flags |= SELECTED;
  175. }
  176.  
  177. struct Memory *NewMemory()
  178. {
  179.     struct Memory *mem;
  180.     struct Remember *key = NULL;
  181.  
  182.     mem = (struct Memory *)AllocRemember(&key, sizeof(struct Memory), MEMF_CLEA
  183. R);
  184.     if (mem)
  185.     {
  186.         mem->Mem = key;
  187.         NewList((struct List *)&mem->Fonts);
  188.         NewList((struct List *)&mem->Lists);
  189.     }
  190.  
  191.     return(mem);
  192. }
  193.  
  194. void Free(mem)
  195. struct Memory *mem;
  196. {
  197.     struct MinNode *mn;
  198.  
  199.     if (mem)
  200.     {
  201.         for (mn = mem->Fonts.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
  202.             CloseFont(((struct FontNode *)mn)->font);
  203.         for (mn = mem->Lists.mlh_Head; mn->mln_Succ; mn = mn->mln_Succ)
  204.             free_ilist((struct ListInfo *)mn);
  205.  
  206.         FreeRemember(&mem->Mem, TRUE);
  207.     }
  208. }
  209.  
  210. void ModSys(f, b, m, font)
  211. long f, b, m;
  212. struct TextAttr *font;
  213. {
  214.     if (f != -1) fore = f;
  215.     if (b != -1) back = b;
  216.     if (m != -1) mode = m;
  217.     if (font)
  218.     {
  219.         ta = font;
  220.         fontopen = FALSE;
  221.     }
  222. }
  223.  
  224. void SetDepth(d)
  225. long d;
  226. {
  227.    depth = d;
  228. }
  229.  
  230. struct Requester *InitReq(left, top, width, height, mem)
  231. long left, top, width, height;
  232. struct Memory *mem;
  233. {
  234.     struct Requester *req;
  235.  
  236.     req = (struct Requester *)AllocRemember(&mem->Mem, sizeof(struct Requester)
  237. , MEMF_CLEAR);
  238.     if (req)
  239.     {
  240.         req->LeftEdge = left; req->TopEdge = top;
  241.         req->Width = width; req->Height = height;
  242.         req->BackFill = back;
  243.     }
  244.  
  245.     return(req);
  246. }
  247.  
  248. boolean SetReqBorder(req, type, mem)
  249. struct Requester *req;
  250. LONG type;
  251. struct Memory *mem;
  252. {
  253.     struct Border *b = NULL;
  254.  
  255.     switch (type)
  256.     {
  257.         case 1:
  258.             if (!AddRectBorder(&b, XDOUBLEMARGIN / 2, YDOUBLEMARGIN / 2, req->W
  259. idth - XDOUBLEMARGIN, req->Height - YDOUBLEMARGIN, mem))
  260.                 break;
  261.         case 0:
  262.             if (!AddRectBorder(&b, 0, 0, req->Width, req->Height, mem))
  263.                 b = NULL;
  264.             break;
  265.         default:
  266.             b = (struct Border *)type;
  267.             break;
  268.     }
  269.  
  270.     return((req->ReqBorder = b) != NULL);
  271. }
  272.  
  273. void SetReqGadgets(req, gl)
  274. struct Requester *req;
  275. struct Gadget *gl;
  276. {
  277.     struct Gadget *g;
  278.  
  279.     for (g = gl; g; g = g->NextGadget)
  280.         g->GadgetType |= REQGADGET;
  281.  
  282.     req->ReqGadget = gl;
  283. }
  284.  
  285. void SetReqText(req, it)
  286. struct Requester *req;
  287. struct IntuiText *it;
  288. {
  289.     req->ReqText = it;
  290. }
  291.  
  292. struct Gadget *AddBox(gl, id, text, flags, act, x, y, w, h, thick, mem)
  293. struct Gadget **gl;
  294. char *text;
  295. long id, flags, act, x, y, w, h, thick;
  296. struct Memory *mem;
  297. {
  298.     BYTE *data;
  299.     struct Gadget *gadg = NULL;
  300.     int i, tl, tx, ty, len = strlen(text);
  301.     struct RastPort rp, rp2;
  302.     struct BitMap bm, bm2;
  303.     struct Image *im, *im2;
  304.  
  305.     if (CheckFont(mem) &&
  306.         (gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
  307.  + 2 * sizeof(struct Image), MEMF_CLEAR)) &&
  308.         (data = (BYTE *)AllocRemember(&mem->Mem, 2 * depth * RASSIZE(w, h), MEM
  309. F_CLEAR | MEMF_CHIP)))
  310.     {
  311.         im2 = (im = (struct Image *)(gadg + 1)) + 1;
  312.  
  313.         InitBitMap(&bm, depth, w, h);
  314.         InitBitMap(&bm2, depth, w, h);
  315.         for (i = 0; i < depth; i++)
  316.         {
  317.             bm.Planes[i] = data;
  318.             bm2.Planes[i] = data + RASSIZE(w, h) * depth;
  319.             data += RASSIZE(w, h);
  320.         }
  321.         InitRastPort(&rp);
  322.         rp.BitMap = &bm;
  323.         InitRastPort(&rp2);
  324.         rp2.BitMap = &bm2;
  325.         SetAPen(&rp, fore);
  326.         SetAPen(&rp2, fore);
  327.  
  328.         im->Width = im2->Width = w;
  329.         im->Height = im2->Height = h;
  330.         im->Depth = im2->Depth = depth;
  331.         im->ImageData = (USHORT *)bm.Planes[0];
  332.         im2->ImageData = (USHORT *)bm2.Planes[0];
  333.         im->PlanePick = im2->PlanePick = 0xff;
  334.  
  335.         SetRast(&rp, back);
  336.         SetRast(&rp2, back);
  337.         DrawRoundedRect(&rp, 0, 0, w, h);
  338.         FillRoundedRect(&rp2, 0, 0, w, h);
  339.         if (thick)
  340.         {
  341.             DrawRoundedRect(&rp, 1, 1, w - 2, h - 2);
  342.             DrawRoundedRect(&rp, 1, 0, w - 2, h);
  343.         }
  344.  
  345.         SetFont(&rp, font);
  346.         SetFont(&rp2, font);
  347.         tl = TextLength(&rp, text, len);
  348.         tx = (w - tl) / 2;
  349.         ty = (h - font->tf_YSize + 1) / 2 + font->tf_Baseline;
  350.         SetDrMd(&rp, JAM1);
  351.         Move(&rp, tx, ty); Text(&rp, text, len);
  352.         SetAPen(&rp2, back); SetDrMd(&rp2, JAM1);
  353.         Move(&rp2, tx, ty); Text(&rp2, text, len);
  354.  
  355.         gadg->LeftEdge = x;
  356.         gadg->TopEdge = y;
  357.         gadg->Width = w;
  358.         gadg->Height = h;
  359.         gadg->GadgetType = BOOLGADGET;
  360.  
  361.         gadg->GadgetRender = (APTR)im;
  362.         gadg->SelectRender = (APTR)im2;
  363.         gadg->GadgetID = id;
  364.         gadg->Flags = GADGHIMAGE | GADGIMAGE | flags;
  365.         gadg->Activation = act;
  366.  
  367.         AppendGadget(gl, gadg);
  368.     }
  369.  
  370.     return(gadg);
  371. }
  372.  
  373. struct Gadget *AddRadio(gl, id, text, side, flags, act, mutex, x, y, w, h, mem)
  374.      
  375. struct Gadget **gl;
  376. char *text;
  377. long id, side, flags, act, x, y, w, h, mutex;
  378. struct Memory *mem;
  379. {
  380.     BYTE *data;
  381.     struct Gadget *gadg = NULL;
  382.     struct IntuiText *it = NULL;
  383.     struct RastPort rp, rp2;
  384.     struct BitMap bm, bm2;
  385.     struct Image *im, *im2;
  386.     int tl, bx, i;
  387.     struct AreaInfo areainf;
  388.     struct TmpRas tmpras;
  389.     BYTE areabuf[4 * 5];
  390.     PLANEPTR plane;
  391.  
  392.     if (AddIntuiText(&it, text, side ? w + GADGTEXTX : 0, 0, mem) &&
  393.         (gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
  394.  + 2 * sizeof(struct Image), MEMF_CLEAR)) &&
  395.         (data = (BYTE *)AllocRemember(&mem->Mem, 2 * depth * RASSIZE(w, h), MEM
  396. F_CLEAR | MEMF_CHIP)))
  397.     {
  398.         tl = IntuiTextLength(it);
  399.         it->TopEdge = (h - font->tf_YSize) / 2;
  400.  
  401.         gadg->LeftEdge = side ? x : x - tl - GADGTEXTX;
  402.         gadg->TopEdge = y;
  403.         gadg->Width = tl + GADGTEXTX + w;
  404.         gadg->Height = h;
  405.         gadg->GadgetType = BOOLGADGET;
  406.         gadg->MutualExclude = mutex;
  407.  
  408.         bx = side ? 0 : tl + GADGTEXTX;
  409.  
  410.         im2 = (im = (struct Image *)(gadg + 1)) + 1;
  411.  
  412.         InitBitMap(&bm, depth, w, h);
  413.         InitBitMap(&bm2, depth, w, h);
  414.         for (i = 0; i < depth; i++)
  415.         {
  416.             bm.Planes[i] = data;
  417.             bm2.Planes[i] = data + RASSIZE(w, h) * depth;
  418.             data += RASSIZE(w, h);
  419.         }
  420.         InitRastPort(&rp);
  421.         rp.BitMap = &bm;
  422.         InitRastPort(&rp2);
  423.         rp2.BitMap = &bm2;
  424.         if (plane = (PLANEPTR)AllocRaster(w, h))
  425.         {
  426.             InitTmpRas(&tmpras, plane, RASSIZE(w, h));
  427.             rp2.TmpRas = &tmpras;
  428.             memset(areabuf, 0, sizeof(areabuf));
  429.             InitArea(&areainf, (short *)areabuf, 4);
  430.             rp2.AreaInfo = &areainf;
  431.  
  432.             SetAPen(&rp, fore);
  433.             SetAPen(&rp2, fore);
  434.  
  435.             im->Width = im2->Width = w;
  436.             im->Height = im2->Height = h;
  437.             im->LeftEdge = im2->LeftEdge = bx;
  438.             im->Depth = im2->Depth = depth;
  439.             im->ImageData = (USHORT *)bm.Planes[0];
  440.             im2->ImageData = (USHORT *)bm2.Planes[0];
  441.             im->PlanePick = im2->PlanePick = 0xff;
  442.  
  443.             SetRast(&rp, back);
  444.             SetRast(&rp2, back);
  445.             DrawEllipse(&rp, w/2, h/2, w/2 - 1, h/2 - 1);
  446.             DrawEllipse(&rp2, w/2, h/2, w/2 - 1, h/2 - 1);
  447.             AreaEllipse(&rp2, w/2, h/2, w/4, h/4);
  448.             AreaEnd(&rp2);
  449.             FreeRaster(plane, w, h);
  450.             rp2.TmpRas = NULL;
  451.             rp2.AreaInfo = NULL;
  452.  
  453.             gadg->GadgetRender = (APTR)im;
  454.             gadg->SelectRender = (APTR)im2;
  455.             gadg->GadgetText = it;
  456.             gadg->GadgetID = id;
  457.             gadg->Flags = GADGHIMAGE | GADGIMAGE | flags;
  458.             gadg->Activation = act;
  459.  
  460.             AppendGadget(gl, gadg);
  461.         }
  462.         else
  463.             gadg = NULL;
  464.     }
  465.     return(gadg);
  466. }
  467.  
  468. struct Gadget *AddOption(gl, id, text, side, flags, act, x, y, w, h, mem)
  469. struct Gadget **gl;
  470. char *text;
  471. long id, side, flags, act, x, y, w, h;
  472. struct Memory *mem;
  473. {
  474.     struct Gadget *gadg = NULL;
  475.     struct IntuiText *it = NULL;
  476.     struct Border *b = NULL, *b2 = NULL;
  477.     int tl, bx, f = fore, ba = back;
  478.  
  479.     if (AddIntuiText(&it, text, side ? w + GADGTEXTX : 0, 0, mem) &&
  480.         (gadg = (struct Gadget *)AllocRemember(&mem->Mem, sizeof(struct Gadget)
  481. , MEMF_CLEAR)))
  482.     {
  483.         gadg->Height = h;
  484.         tl = IntuiTextLength(it);
  485.         it->TopEdge = (h - font->tf_YSize) / 2;
  486.  
  487.         gadg->LeftEdge = side ? x : x - tl - GADGTEXTX;
  488.         gadg->TopEdge = y;
  489.         gadg->Width = tl + 4 + w;
  490.         gadg->GadgetType = BOOLGADGET;
  491.  
  492.         bx = side ? 0 : tl + GADGTEXTX;
  493.         if (AddLineBorder(&b, bx, 0, bx + w - 1, h - 1, mem) &&
  494.             AddLineBorder(&b, bx + w - 1, 0, bx, h - 1, mem) &&
  495.             AddRectBorder(&b, bx, 0, w, h, mem) &&
  496.             (fore = ba, back = f, AddLineBorder(&b2, bx, 0, bx + w - 1, h - 1,
  497. mem)) &&
  498.             AddLineBorder(&b2, bx + w - 1, 0, bx, h - 1, mem) &&
  499.             (fore = f, back = ba, AddRectBorder(&b2, bx, 0, w, h, mem)))
  500.         {
  501.             gadg->GadgetRender = (APTR)b2;
  502.             gadg->SelectRender = (APTR)b;
  503.             gadg->GadgetText = it;
  504.             gadg->GadgetID = id;
  505.             gadg->Flags = GADGHIMAGE | flags;
  506.             gadg->Activation = TOGGLESELECT | act;
  507.  
  508.             AppendGadget(gl, gadg);
  509.         }
  510.         else
  511.             gadg = NULL;
  512.     }
  513.  
  514.     fore = f; back = ba;
  515.     return(gadg);
  516. }
  517.  
  518. struct Gadget *AddText(struct Gadget **gl, long id, char *text, long above, cha
  519. r *buf, long maxlen, long undo, long flags, long act, long x, long y, long w, lo
  520. ng h, long noborder, struct Memory *mem)
  521. {
  522.     BYTE *data;
  523.     struct StringInfo *si;
  524.     struct Gadget *gadg = NULL;
  525.     struct IntuiText *it = NULL;
  526.     int tl;
  527.     struct Border *b = NULL;
  528.     char *undobuf;
  529.  
  530.     data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Gadget) + sizeof(stru
  531. ct StringInfo) + (undo ? maxlen + 1: 0), MEMF_CLEAR);
  532.     if (data)
  533.     {
  534.         gadg = (struct Gadget *)data;
  535.         si = (struct StringInfo *)(gadg + 1);
  536.         undobuf = undo ? data + sizeof(struct Gadget) + sizeof(struct StringInf
  537. o) : NULL;
  538.  
  539.         if (AddIntuiText(&it, text, 0, 0, mem))
  540.         {
  541.             tl = IntuiTextLength(it);
  542.             if (above)
  543.             {
  544.                 it->TopEdge = -font->tf_YSize - GADGTEXTY;
  545.                 it->LeftEdge = 0;
  546.             }
  547.             else
  548.             {
  549.                 it->TopEdge = h - font->tf_YSize - 2;
  550.                 it->LeftEdge = -tl - GADGTEXTX;
  551.             }
  552.  
  553.             gadg->LeftEdge = x;
  554.             gadg->TopEdge = y;
  555.             gadg->Width = w;
  556.             gadg->Height = h;
  557.             gadg->GadgetType = STRGADGET;
  558.  
  559.             if (noborder || AddRectBorder(&b, -TEXTBORDERX + 1, -TEXTBORDERY +
  560. 1, w + TEXTBORDERX, h + TEXTBORDERY, mem))
  561.             {
  562.                 gadg->GadgetRender = (APTR)b;
  563.                 gadg->GadgetText = it;
  564.                 gadg->GadgetID = id;
  565.                 gadg->Flags = GADGHCOMP | flags;
  566.                 gadg->Activation = act;
  567.                 gadg->SpecialInfo = (APTR)si;
  568.  
  569.                 si->Buffer = buf;
  570.                 si->UndoBuffer = undobuf;
  571.                 si->MaxChars = maxlen;
  572.  
  573.                 AppendGadget(gl, gadg);
  574.             }
  575.             else
  576.                 gadg = NULL;
  577.         }
  578.         else
  579.             gadg = NULL;
  580.     }
  581.  
  582.     return(gadg);
  583. }
  584.  
  585. struct Gadget *AddSlider(struct Gadget **gl, long id, long act, long x, long y,
  586.  long w, long h, long vert, long knobsize, struct Memory *mem)
  587. {
  588.     BYTE *data;
  589.     struct Gadget *gg = NULL;
  590.     struct PropInfo *info;
  591.     struct Image *im;
  592.  
  593.     data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Gadget) + sizeof(stru
  594. ct PropInfo) + sizeof(struct Image), MEMF_CLEAR);
  595.     if (data)
  596.     {
  597.         gg = (struct Gadget *)data;
  598.         info = (struct PropInfo *)(data + sizeof(struct Gadget));
  599.         im = (struct Image *)(data + sizeof(struct Gadget) + sizeof(struct Prop
  600. Info));
  601.  
  602.         gg->LeftEdge = x;
  603.         gg->TopEdge = y;
  604.         gg->Width = w;
  605.         gg->Height = h;
  606.         gg->Flags = GADGHCOMP | GADGIMAGE |
  607.                     (y < 0 ? GRELBOTTOM : 0) |
  608.                     (x < 0 ? GRELRIGHT : 0) |
  609.                     (w < 0 ? GRELWIDTH : 0) |
  610.                     (h < 0 ? GRELHEIGHT : 0);
  611.         gg->Activation = act;
  612.         gg->GadgetType = PROPGADGET;
  613.         gg->GadgetRender = (APTR)im; /* dummy image, why ? */
  614.         gg->SpecialInfo = (APTR)info;
  615.         gg->GadgetID = id;
  616.  
  617.         info->Flags = AUTOKNOB |
  618.                       (vert ? FREEVERT : FREEHORIZ);
  619.         if (vert) info->VertBody = knobsize;
  620.         else info->HorizBody = knobsize;
  621.  
  622.         AppendGadget(gl, gg);
  623.     }
  624.     return(gg);
  625. }
  626.  
  627. /* BUG: Arrows don't use selected colours */
  628. struct ListInfo *AddList(struct Gadget **gl, long id, char *text, struct List *
  629. list, char *buf, long len, long flags, long act, long x, long y, long w, long h,
  630.  long noborder, struct Memory *mem)
  631. {
  632.     long ok = FALSE;
  633.     struct ListInfo *li;
  634.     int i;
  635.     long nb;
  636.     int a = font->tf_YSize;
  637.     int dispchars = (w - 15 - 3) / font->tf_XSize;
  638.     int nblines = (h - 2) / a;
  639.  
  640.     if (CheckFont(mem) &&
  641.         (li = (struct ListInfo *)AllocRemember(&mem->Mem, sizeof(struct ListInf
  642. o) + dispchars + 1, MEMF_CLEAR)))
  643.     {
  644.         char *spaces = (char *)(li + 1);
  645.  
  646.         memset(spaces, ' ', dispchars);
  647.         spaces[dispchars] = '\0';
  648.  
  649.         AddHead((struct List *)&mem->Lists, (struct Node *)li);
  650.         if (nblines >= 5 && a * (nblines - 2) - 26 > 20 && w > 15 + 3 + 32)
  651.         {
  652.             w = font->tf_XSize * dispchars + 15 + 3;
  653.             h = a * nblines + 2;
  654.  
  655.             li->buf = buf;
  656.             li->len = len;
  657.             li->list = list;
  658.             li->pos = 0;
  659.             li->current = -1;
  660.             li->visible = nblines - 2;
  661.             li->dispchars = dispchars;
  662.             li->clickpos = -1;
  663.  
  664.             if ((li->nb = nb = build_ilist(li)) != -1 &&
  665.                 AddIntuiText(&li->blank, spaces, 0, 0, mem))
  666.             {
  667.                 struct Gadget *arrow1, *arrow2, *sld;
  668.                 struct Border *b = NULL;
  669.                 long knobsize;
  670.  
  671.                 if (nb == 0)
  672.                     knobsize = 0xffff;
  673.                 else
  674.                 {
  675.                     knobsize = 0xffff * li->exists;
  676.                     knobsize /= nb;
  677.                 }
  678.  
  679.                 if ((sld = AddSlider(gl, id, RELVERIFY, x + w - 16, y + 13, 15,
  680.  h - 2 * a - 26, TRUE, knobsize, mem)) &&
  681.                     (arrow1 = (struct Gadget *)AllocRemember(&mem->Mem, 3 * siz
  682. eof(struct Gadget), MEMF_CLEAR)) &&
  683.                     AddRectBorder(&b, 0, 0, w, h - 2 * a, mem) &&
  684.                     AddRectBorder(&b, w - 17, 12, 17, h - 2 * a - 24, mem) &&
  685.                     AddLineBorder(&b, w - 17, 0, w - 17, h - 2 * a - 1, mem))
  686.                 {
  687.                     struct Gadget *strg, *cadre;
  688.                     int tx;
  689.  
  690.                     sld->UserData = (APTR)li;
  691.                     li->sld = sld;
  692.                     arrow2 = arrow1 + 1;
  693.                     arrow1->TopEdge = y + 1;
  694.                     arrow1->LeftEdge = x + w - 16;
  695.                     arrow1->Width = 15;
  696.                     arrow1->Height = 11;
  697.                     arrow1->Flags = GADGHCOMP | GADGIMAGE;
  698.                     arrow1->Activation = GADGIMMEDIATE | RELVERIFY;
  699.                     arrow1->GadgetType = BOOLGADGET;
  700.                     arrow1->GadgetRender = (APTR)&up_img;
  701.                     arrow1->UserData = (APTR)li;
  702.                     arrow1->GadgetID = id;
  703.                     AppendGadget(gl, arrow1);
  704.  
  705.                     li->arrow1 = arrow1;
  706.                     arrow2->LeftEdge = x + w - 16;
  707.                     arrow2->TopEdge = y + h - 2 * a - 1 - 11;
  708.                     arrow2->Width = 15;
  709.                     arrow2->Height = 11;
  710.                     arrow2->Flags = GADGHCOMP | GADGIMAGE;
  711.                     arrow2->Activation = GADGIMMEDIATE | RELVERIFY;
  712.                     arrow2->GadgetType = BOOLGADGET;
  713.                     arrow2->GadgetRender = (APTR)&down_img;
  714.                     arrow2->UserData = (APTR)li;
  715.                     arrow2->GadgetID = id;
  716.                     AppendGadget(gl, arrow2);
  717.                     li->arrow2 = arrow2;
  718.  
  719.                     cadre = arrow2 + 1;
  720.                     cadre->LeftEdge = x;
  721.                     cadre->TopEdge = y;
  722.                     cadre->Width = 1;
  723.                     cadre->Height = 1;
  724.                     cadre->Flags = GADGHNONE;
  725.                     cadre->GadgetType = BOOLGADGET;
  726.                     cadre->GadgetRender = (APTR)b;
  727.                     cadre->UserData = (APTR)li;
  728.                     cadre->GadgetID = id;
  729.                     AppendGadget(gl, cadre);
  730.  
  731.                     tx = font->tf_XSize * strlen(text);
  732.                     if (tx > w - 32) tx = w - 32;
  733.                     if (strg = AddText(gl, id, text, FALSE, buf, len, TRUE, fla
  734. gs, act | GADGIMMEDIATE, x + tx + GADGTEXTX, y + h - a - 2, w - tx - GADGTEXTX,
  735. a + 2, noborder, mem))
  736.                     {
  737.                         GArray *bl;
  738.  
  739.                         strg->UserData = (APTR)li;
  740.                         li->strg = strg;
  741.  
  742.                         if (bl = (GArray *)AllocRemember(&mem->Mem, li->visible
  743.  * sizeof(struct Gadget), MEMF_CLEAR))
  744.                         {
  745.                             li->glist = bl;
  746.                             for (i = 0; i < li->visible; i++)
  747.                             {
  748.                                 struct Gadget *gg = &(*bl)[i];
  749.  
  750.                                 gg->LeftEdge = x + 1;
  751.                                 gg->TopEdge = y + i * a + 1;
  752.                                 gg->Width = w - 18;
  753.                                 gg->Height = a;
  754.                                 gg->Flags = GADGHCOMP;
  755.                                 gg->Activation = GADGIMMEDIATE;
  756.                                 gg->GadgetType = BOOLGADGET;
  757.                                 gg->UserData = (APTR)li;
  758.                                 gg->GadgetID = id;
  759.                                 AppendGadget(gl, gg);
  760.                             }
  761.                             recalc_glist(li);
  762.                             ok = TRUE;
  763.                         }
  764.                     }
  765.                 }
  766.             }
  767.         }
  768.     }
  769.     return ok ? li : NULL;
  770. }
  771.  
  772. long ModifyList(struct Gadget *gg, struct Requester *req, struct Window *win, l
  773. ong up)
  774. {
  775.     struct ListInfo *li = (struct ListInfo *)gg->UserData;
  776.     int change = FALSE, ret = 0;
  777.  
  778.     switch (gg->GadgetType & ~GADGETTYPE)
  779.     {
  780.         case STRGADGET:
  781.             if (!up && li->current != -1)
  782.             {
  783.                 change = TRUE;
  784.                 (*li->glist)[li->current - li->pos].Flags &= ~SELECTED;
  785.                 li->current = li->clickpos = -1;
  786.             }
  787.             else if (up) ret = 1;
  788.             break;
  789.         case PROPGADGET:
  790.             {
  791.                 struct PropInfo *pi = (struct PropInfo *)gg->SpecialInfo;
  792.  
  793.                 if (li->current != -1) (*li->glist)[li->current - li->pos].Flag
  794. s &= ~SELECTED;
  795.  
  796.                 li->pos = (pi->VertPot + 1) * (li->nb - li->exists) >> 16;
  797.                 recalc_glist(li);
  798.                 change = TRUE;
  799.             }
  800.             break;
  801.         case BOOLGADGET:
  802.             if (gg == li->arrow1 || gg == li->arrow2)
  803.             {
  804.                 if (up)
  805.                 {
  806.                     long newpos;
  807.  
  808.                     if (li->current != -1) (*li->glist)[li->current - li->pos].
  809. Flags &= ~SELECTED;
  810.                     newpos = li->pos + (gg == li->arrow1 ? -1 : 1);
  811.                     if (newpos >= 0 && newpos <= li->nb - li->exists)
  812.                     {
  813.                         struct PropInfo *pi = (struct PropInfo *)li->sld->Speci
  814. alInfo;
  815.                         long newpot;
  816.  
  817.                         li->pos = newpos;
  818.                         newpot = 0xffff * li->pos;
  819.                         newpot /= li->nb - li->exists;
  820.                         NewModifyProp(li->sld, win, req, pi->Flags, 0, newpot,
  821. 0, pi->VertBody, 1);
  822.                         recalc_glist(li);
  823.                         change = TRUE;
  824.                     }
  825.                 }
  826.             }
  827.             else
  828.             {
  829.                 int i, pos = -1;
  830.  
  831.                 for (i = 0; i < li->exists; i++)
  832.                     if (gg == &(*li->glist)[i])
  833.                     {
  834.                         pos = i;
  835.                         break;
  836.                     }
  837.                 if (pos != -1)
  838.                 {
  839.                     ULONG secs, micros;
  840.                     struct Node *scan;
  841.  
  842.                     CurrentTime(&secs, µs);
  843.                     if (li->current != -1) (*li->glist)[li->current - li->pos].
  844. Flags &= ~SELECTED;
  845.                     li->current = li->pos + pos;
  846.                     (*li->glist)[pos].Flags |= SELECTED;
  847.                     change = TRUE;
  848.                     li->buf[li->len - 1] = '\0';
  849.                     for (i = 0, scan = li->list->lh_Head; i < li->current; i++,
  850.  scan = scan->ln_Succ)
  851.                         ;
  852.                     strncpy(li->buf, scan->ln_Name, li->len - 1);
  853.                     RefreshGList(li->strg, win, req, 1);
  854.  
  855.                     ret = li->clickpos == li->current && DoubleClick(li->clicks
  856. ecs, li->clickmics, secs, micros) ? 2 : 1;
  857.                     li->clickpos = li->current;
  858.                     li->clicksecs = secs;
  859.                     li->clickmics = micros;
  860.                 }
  861.             }
  862.     }
  863.     if (change) RefreshGList(&(*li->glist)[0], win, req, li->exists);
  864.  
  865.     return ret;
  866. }
  867.  
  868. long ChangeList(struct ListInfo *li, struct List *list, struct Requester *req,
  869. struct Window *win)
  870. {
  871.     struct PropInfo *pi = (struct PropInfo *)li->sld->SpecialInfo;
  872.     long knobsize;
  873.  
  874.     free_ilist(li);
  875.     li->list = list;
  876.     if ((li->nb = build_ilist(li)) != -1)
  877.     {
  878.         if (li->current != -1) (*li->glist)[li->current - li->pos].Flags &= ~SE
  879. LECTED;
  880.  
  881.         li->pos = 0;
  882.         li->current = -1;
  883.         li->clickpos = -1;
  884.  
  885.         if (li->nb == 0)
  886.             knobsize = 0xffff;
  887.         else
  888.         {
  889.             knobsize = 0xffff * li->exists;
  890.             knobsize /= li->nb;
  891.         }
  892.         NewModifyProp(li->sld, win, req, pi->Flags, 0, 0, 0, knobsize, 1);
  893.  
  894.         recalc_glist(li);
  895.         RefreshGList(&(*li->glist)[0], win, req, li->visible);
  896.  
  897.         return TRUE;
  898.     }
  899.     return FALSE;
  900. }
  901.  
  902. struct Gadget *ListStr(struct ListInfo *li)
  903. {
  904.     return li->strg;
  905. }
  906.  
  907. struct IntuiText *AddIntuiText(it, str, x, y, mem)
  908. struct IntuiText **it;
  909. char *str;
  910. long x, y;
  911. struct Memory *mem;
  912. {
  913.     struct IntuiText *intui = NULL;
  914.  
  915.     if (CheckFont(mem))
  916.     {
  917.         intui = (struct IntuiText *)AllocRemember(&mem->Mem, sizeof(struct Intu
  918. iText), MEMF_CLEAR);
  919.         if (intui)
  920.         {
  921.             intui->FrontPen = fore; intui->BackPen = back;
  922.             intui->DrawMode = mode;
  923.             intui->LeftEdge = x; intui->TopEdge = y;
  924.             intui->ITextFont = ta;
  925.             intui->IText = str;
  926.  
  927.             AppendText(it, intui);
  928.         }
  929.     }
  930.  
  931.     return(intui);
  932. }
  933.  
  934. struct Border *AddLineBorder(struct Border **border, long x0, long y0, long x1,
  935.  long y1, struct Memory *mem)
  936. {
  937.     BYTE *data;
  938.     struct Border *bb = NULL;
  939.     WORD *vert;
  940.  
  941.     data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Border) + 2 * 2 * siz
  942. eof(WORD), MEMF_CLEAR);
  943.     if (data) {
  944.         bb = (struct Border *)data;
  945.         vert = (WORD *)(data + sizeof(struct Border));
  946.  
  947.         bb->FrontPen = fore; bb->BackPen = back;
  948.         bb->DrawMode = mode;
  949.         bb->LeftEdge = 0; bb->TopEdge = 0;
  950.         bb->Count = 2;
  951.         bb->XY = vert;
  952.  
  953.         vert[0] = x0; vert[1] = y0;
  954.         vert[2] = x1; vert[3] = y1;
  955.  
  956.         AppendBorder(border, bb);
  957.     }
  958.  
  959.     return(bb);
  960. }
  961.  
  962. struct Border *AddRectBorder(border, x, y, w, h, mem)
  963. struct Border **border;
  964. long x, y, w, h;
  965. struct Memory *mem;
  966. {
  967.     BYTE *data;
  968.     struct Border *bb = NULL;
  969.     WORD *vert;
  970.  
  971.     data = (BYTE *)AllocRemember(&mem->Mem, sizeof(struct Border) + 5 * 2 * siz
  972. eof(WORD), MEMF_CLEAR);
  973.     if (data) {
  974.         bb = (struct Border *)data;
  975.         vert = (WORD *)(data + sizeof(struct Border));
  976.  
  977.         bb->FrontPen = fore; bb->BackPen = back;
  978.         bb->DrawMode = mode;
  979.         bb->LeftEdge = x; bb->TopEdge = y;
  980.         bb->Count = 5;
  981.         bb->XY = vert;
  982.  
  983.         vert[1 * 2 + 0] = w - 1;
  984.         vert[2 * 2 + 0] = w - 1;
  985.         vert[2 * 2 + 1] = h - 1;
  986.         vert[3 * 2 + 1] = h - 1;
  987.  
  988.         AppendBorder(border, bb);
  989.     }
  990.  
  991.     return(bb);
  992. }
  993.  
  994. struct Menu *AddMenu(struct Menu **ml, struct Screen *scr, char *text, long fla
  995. gs, struct Memory *mem)
  996. {
  997.     struct Screen look;
  998.     struct TextFont *scrfont;
  999.     struct Menu *menu = NULL, *prev;
  1000.  
  1001.     if (GetScreenData((char *)&look, sizeof(struct Screen), scr == NULL ? WBENC
  1002. HSCREEN : CUSTOMSCREEN, scr))
  1003.         if (scrfont = OpenDiskFont(look.Font))
  1004.         {
  1005.             if (menu = (struct Menu *)AllocRemember(&mem->Mem, sizeof(struct Me
  1006. nu), MEMF_CLEAR))
  1007.             {
  1008.                 menu->MenuName = text;
  1009.                 menu->Flags = flags;
  1010.                 menu->Height = scrfont->tf_YSize + 1;
  1011.                 menu->Width = scrfont->tf_XSize * strlen(text) + MENUMARGIN / 2
  1012. ;
  1013.  
  1014.                 if (*ml == NULL)
  1015.                 {
  1016.                     menu->LeftEdge = 0;
  1017.                     *ml = menu;
  1018.                 }
  1019.                 else
  1020.                 {
  1021.                     for (prev = *ml; prev->NextMenu; prev = prev->NextMenu) ;
  1022.                     prev->NextMenu = menu;
  1023.                     menu->LeftEdge = prev->LeftEdge + prev->Width + MENUMARGIN;
  1024.      
  1025.                 }
  1026.             }
  1027.             CloseFont(scrfont);
  1028.         }
  1029.     return menu;
  1030. }
  1031.  
  1032. /* Assumes HIRES screen (for COMMWIDTH) */
  1033. struct MenuItem *AddItem(struct Menu *menu, char *text, long flags, long mutex,
  1034.  long cmd, long sub, struct Memory *mem)
  1035. {
  1036.     struct MenuItem *item = NULL, *prev;
  1037.     struct IntuiText *it = NULL;
  1038.     WORD width;
  1039.  
  1040.     if (AddIntuiText(&it, text, TEXTMARGIN / 2, TEXTGAP / 2, mem))
  1041.     {
  1042.         if (item = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct Me
  1043. nuItem), MEMF_CLEAR))
  1044.         {
  1045.             item->LeftEdge = 0;
  1046.             width = IntuiTextLength(it) + TEXTMARGIN;
  1047.             item->Flags = flags | ITEMTEXT;
  1048.             item->Height = font->tf_YSize + TEXTGAP;
  1049.             item->MutualExclude = mutex;
  1050.             item->ItemFill = (APTR)it;
  1051.             if (cmd)
  1052.             {
  1053.                 item->Flags |= COMMSEQ;
  1054.                 width += COMMWIDTH + font->tf_XSize;
  1055.                 item->Command = cmd;
  1056.             }
  1057.             if (sub)
  1058.                 width += 2 * font->tf_XSize + TEXTMARGIN / 2;
  1059.  
  1060.             if (width < MINITEMWIDTH) width = MINITEMWIDTH;
  1061.  
  1062.             if (menu->FirstItem)
  1063.             {
  1064.                 for (prev = menu->FirstItem; prev->NextItem; prev = prev->NextI
  1065. tem) ;
  1066.                 item->TopEdge = prev->TopEdge + prev->Height;
  1067.                 prev->NextItem = item;
  1068.                 if (prev->Width > width)
  1069.                     item->Width = prev->Width;
  1070.                 else
  1071.                     for (prev = menu->FirstItem; prev; prev = prev->NextItem)
  1072.                     {
  1073.                         struct IntuiText *msg;
  1074.  
  1075.                         if ((prev->Flags & ITEMTEXT) == 0) /* A rule */
  1076.                             ((struct Image *)(prev->ItemFill))->Width = width -
  1077.  RULEMARGIN;
  1078.                         else if ((msg = ((struct IntuiText *)(prev->ItemFill))-
  1079. >NextText) != NULL) /* A SubItem header */
  1080.                             msg->LeftEdge += width - prev->Width;
  1081.  
  1082.                         prev->Width = width;
  1083.                     }
  1084.             }
  1085.             else
  1086.             {
  1087.                 menu->FirstItem = item;
  1088.                 item->TopEdge = 0;
  1089.                 item->Width = width;
  1090.             }
  1091.             if (sub && !AddIntuiText(&it, ".", item->Width - TEXTMARGIN / 2 - f
  1092. ont->tf_XSize, TEXTGAP / 2, mem))
  1093.                 item = NULL;
  1094.         }
  1095.     }
  1096.     return item;
  1097. }
  1098.  
  1099. /* Assumes HIRES screen (for COMMWIDTH) */
  1100. struct MenuItem *AddSub(struct MenuItem *item, char *text, long flags, long mut
  1101. ex, long cmd, struct Memory *mem)
  1102. {
  1103.     struct MenuItem *subitem = NULL, *prev;
  1104.     struct IntuiText *it = NULL;
  1105.     WORD width;
  1106.  
  1107.     if (AddIntuiText(&it, text, TEXTMARGIN / 2, TEXTGAP / 2, mem))
  1108.     {
  1109.         if (subitem = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct
  1110.  MenuItem), MEMF_CLEAR))
  1111.         {
  1112.             subitem->LeftEdge = SUBX;
  1113.             width = IntuiTextLength(it) + TEXTMARGIN;
  1114.             subitem->Flags = flags | ITEMTEXT;
  1115.             subitem->Height = font->tf_YSize + TEXTGAP;
  1116.             subitem->MutualExclude = mutex;
  1117.             subitem->ItemFill = (APTR)it;
  1118.             if (cmd)
  1119.             {
  1120.                 subitem->Flags |= COMMSEQ;
  1121.                 width += COMMWIDTH + font->tf_XSize;
  1122.                 subitem->Command = cmd;
  1123.             }
  1124.             if (width < MINITEMWIDTH) width = MINITEMWIDTH;
  1125.  
  1126.             if (item->SubItem)
  1127.             {
  1128.                 for (prev = item->SubItem; prev->NextItem; prev = prev->NextIte
  1129. m) ;
  1130.                 subitem->TopEdge = prev->TopEdge + prev->Height;
  1131.                 prev->NextItem = subitem;
  1132.                 if (prev->Width > width)
  1133.                     subitem->Width = prev->Width;
  1134.                 else
  1135.                     for (prev = item->SubItem; prev; prev = prev->NextItem)
  1136.                         prev->Width = width;
  1137.             }
  1138.             else
  1139.             {
  1140.                 item->SubItem = subitem;
  1141.                 subitem->TopEdge = font->tf_YSize / 2 + 1;
  1142.                 subitem->Width = width;
  1143.             }
  1144.         }
  1145.     }
  1146.     return subitem;
  1147. }
  1148. /* Inspired by Stuart Ferguson's code */
  1149. struct MenuItem *AddRule(struct Menu *menu, struct Memory *mem)
  1150. {
  1151.     struct MenuItem *item = NULL, *prev;
  1152.     struct Image *img;
  1153.  
  1154.     if ((img = (struct Image *)AllocRemember(&mem->Mem, sizeof(struct Image), M
  1155. EMF_CLEAR)) &&
  1156.         (item = (struct MenuItem *)AllocRemember(&mem->Mem, sizeof(struct MenuI
  1157. tem), MEMF_CLEAR)))
  1158.     {
  1159.         item->LeftEdge = 0;
  1160.         item->Flags = ITEMENABLED | HIGHNONE;
  1161.         item->Height = RULEGAP + RULEHEIGHT;
  1162.         item->MutualExclude = 0;
  1163.         item->ItemFill = (APTR)img;
  1164.  
  1165.         if (menu->FirstItem)
  1166.         {
  1167.             for (prev = menu->FirstItem; prev->NextItem; prev = prev->NextItem)
  1168.  ;
  1169.             item->TopEdge = prev->TopEdge + prev->Height;
  1170.             prev->NextItem = item;
  1171.             item->Width = prev->Width;
  1172.         }
  1173.         else
  1174.         {
  1175.             menu->FirstItem = item;
  1176.             item->TopEdge = 0;
  1177.             item->Width = MINITEMWIDTH;
  1178.         }
  1179.         img->LeftEdge = RULEMARGIN / 2;
  1180.         img->TopEdge = RULEGAP / 2;
  1181.         img->Width = item->Width - RULEMARGIN;
  1182.         img->Height = RULEHEIGHT;
  1183.         img->Depth = depth;
  1184.         img->ImageData = NULL;
  1185.         img->PlanePick = 0;
  1186.         img->PlaneOnOff = fore;
  1187.     }
  1188.     return item;
  1189. }
  1190.  
  1191. boolean CheckFont(mem)
  1192. struct Memory *mem;
  1193. {
  1194.     struct FontNode *fn;
  1195.  
  1196.     if (ta == NULL) fontopen = TRUE;
  1197.     if (!fontopen)
  1198.     {
  1199.         font = (struct TextFont *)OpenDiskFont(ta);
  1200.         if (font)
  1201.         {
  1202.             fn = (struct FontNode *)AllocRemember(&mem->Mem, sizeof(struct Font
  1203. Node), MEMF_CLEAR);
  1204.             if (fn)
  1205.             {
  1206.                 fn->font = font;
  1207.                 AddHead((struct List *)&mem->Fonts, (struct Node *)fn);
  1208.                 fontopen = TRUE;
  1209.             }
  1210.             else CloseFont(font);
  1211.         }
  1212.     }
  1213.  
  1214.     return(fontopen);
  1215. }
  1216.  
  1217. void AppendGadget(gl, gg)
  1218. struct Gadget **gl, *gg;
  1219. {
  1220.     struct Gadget *gadg;
  1221.  
  1222.     if (*gl == NULL) *gl = gg;
  1223.     else
  1224.     {
  1225.         gadg = *gl;
  1226.         while (gadg->NextGadget) gadg = gadg->NextGadget;
  1227.         gadg->NextGadget = gg;
  1228.     }
  1229. }
  1230.  
  1231. void AppendBorder(bl, bb)
  1232. struct Border **bl, *bb;
  1233. {
  1234.     struct Border *bord;
  1235.  
  1236.     if (*bl == NULL) *bl = bb;
  1237.     else
  1238.     {
  1239.         bord = *bl;
  1240.         while (bord->NextBorder) bord = bord->NextBorder;
  1241.         bord->NextBorder = bb;
  1242.     }
  1243. }
  1244.  
  1245. void AppendText(itl, txt)
  1246. struct IntuiText **itl, *txt;
  1247. {
  1248.     struct IntuiText *intui;
  1249.  
  1250.     if (*itl == NULL) *itl = txt;
  1251.     else
  1252.     {
  1253.         intui = *itl;
  1254.         while (intui->NextText) intui = intui->NextText;
  1255.         intui->NextText = txt;
  1256.     }
  1257. }
  1258.  
  1259. #define Line(rp, x1, y1, x2, y2) { Move((rp), (x1), (y1)); Draw((rp), (x2), (y2
  1260. )); }
  1261.  
  1262. void DrawRect(rp, x, y, w, h)
  1263. struct RastPort *rp;
  1264. long x, y, w, h;
  1265. {
  1266.     Move(rp, x, y);
  1267.     Draw(rp, x + w - 1, y);
  1268.     Draw(rp, x + w - 1, y + h - 1);
  1269.     Draw(rp, x, y + h - 1);
  1270.     Draw(rp, x, y);
  1271. }
  1272.  
  1273. void DrawRoundedRect(rp, x, y, w, h)
  1274. struct RastPort *rp;
  1275. long x, y, w, h;
  1276. {
  1277.     int x2 = x + w - 1, y2 = y + h - 1;
  1278.  
  1279.     Line(rp, x + 5, y, x2 - 5, y); Line(rp, x + 5, y2, x2 - 5, y2);
  1280.     Line(rp, x, y + 5, x, y2 - 4); Line(rp, x2, y + 5, x2, y2 - 4);
  1281.     WritePixel(rp, x + 4, y + 1); WritePixel(rp, x + 3, y + 1); WritePixel(rp,
  1282. x + 2, y + 2); WritePixel(rp, x + 1, y + 3); WritePixel(rp, x + 1, y + 4);
  1283.     WritePixel(rp, x + 4, y2 - 1); WritePixel(rp, x + 3, y2 - 1); WritePixel(rp
  1284. , x + 2, y2 - 2); WritePixel(rp, x + 1, y2 - 3); WritePixel(rp, x + 1, y2 - 4);
  1285.     WritePixel(rp, x2 - 4, y + 1); WritePixel(rp, x2 - 3, y + 1); WritePixel(rp
  1286. , x2 - 2, y + 2); WritePixel(rp, x2 - 1, y + 3); WritePixel(rp, x2 - 1, y + 4);
  1287.     WritePixel(rp, x2 - 4, y2 - 1); WritePixel(rp, x2 - 3, y2 - 1); WritePixel(
  1288. rp, x2 - 2, y2 - 2); WritePixel(rp, x2 - 1, y2 - 3); WritePixel(rp, x2 - 1, y2 -
  1289.  4);
  1290. }
  1291.  
  1292. void FillRoundedRect(rp, x, y, w, h)
  1293. struct RastPort *rp;
  1294. long x, y, w, h;
  1295. {
  1296.     int x2 = x + w - 1, y2 = y + h - 1;
  1297.  
  1298.     RectFill(rp, x, y + 5, x2, y2 - 5);
  1299.     Line(rp, x + 1, y + 4, x2 - 1, y + 4); Line(rp, x + 1, y + 3, x2 - 1, y + 3
  1300. ); Line(rp, x + 2, y + 2, x2 - 2, y + 2); Line(rp, x + 4, y + 1, x2 - 4, y + 1);
  1301.      
  1302.     Line(rp, x + 1, y2 - 4, x2 - 1, y2 - 4); Line(rp, x + 1, y2 - 3, x2 - 1, y2
  1303.  - 3); Line(rp, x + 2, y2 - 2, x2 - 2, y2 - 2); Line(rp, x + 4, y2 - 1, x2 - 4,
  1304. y2 - 1);
  1305. }
  1306.  
  1307.